﻿/*
 * protocol_mbus.c
 *
 *  Created on: 2019.05.30
 *      Author: djy
 */

#include <stdint.h>
#include "protocol_mbus.h"
#include "discovery_meter.h"
#include <string.h>
#include "comfun.h"
#include <stdio.h>
#include "config.h"
/*
搜表流程：
1、创建搜表事件discover_meter_event  discover_meter;
2、调用discovery_start(&discover_meter，10);设置搜索数目，启动搜表
3、discovery_meter_hook_10ms()中发送搜表报文、解析回复报文、遍历二叉树。
*/
#define SINGLE    ( 1 )
#define NONE      (-1 )
#define COLLIDE   (-2 )
#define WAIT      (-3 )
#define WAIT_TIME (80)//发送搜表报文间隔时间  单位10ms
#define MASS_TIME (26)//MBUS总线杂波等待时间  单位10ms
static discover_meter_event discover_meter =
{
    .status = SEARCH_END,
    .res = SEARCH_NONE,
    .meter_nums = 0,
    .found_nums = 0,
};
static uint8_t wildcard_bak[DISCOVERY_MAX_LAYER];
char meterNum2[][DISCOVERY_MAX_LAYER+1]=
{
    "8881234567",//不用
    "1810300180",
    "1810300021",
    "1810300141",
    "1810300091",
    "1810300052",
    "1810300053",
    "1810300056",
    "1810300148",
    "1810300149",
    "1810300089",
    "0000000009",
    "0000000010",
    "0000000011",
    "0000000012",
};

static int8_t compare_meter_addr(const char addr[], const unsigned char match[])
{
    int i;


    for(i = DISCOVERY_MAX_LAYER - 1; i >= 0 ; i--)
    {
        char start, end;
        start = (char)((match[i] >> 4)& 0x0F) + '0';//转换成字符
        end = (char)(match[i] & 0x0F) + '0';//转成字符

        if((start <= addr[i]) && (addr[i]<= end))//地址位 在区间范围内
        {
            continue; //检查下一位
        }
        else
        {
            return -1;// 第i位地址不在区间内
        }
    }
    return 0;
}

static uint8_t  cnt_09_in_wildcard_reverse(uint8_t str[])
{
    uint8_t cnt = 0;
    int i=0;
    for(i = DISCOVERY_MAX_LAYER - 1; i > 0; i--)
    {
        if(str[i] == 0x09)
            cnt++;
        else
            break;

    }
    return cnt;
}

void search_meter_start(int nums)//
{
#if DISCOVERY_DEBUG
    DEBUG("device cnt:%d\n",nums);
#endif
    memset(wildcard_bak,0x09,DISCOVERY_MAX_LAYER);
    wildcard_bak[0] = 0x00;
    discovery_init_and_start(&discover_meter,nums);
}

static int  discovery_meter_proto_handler(uint8_t wildcard[])
{
       static uint32_t timer_tick = 0;
       if(timer_tick ==0)
         {
             //根据wildcard 发送搜表报文
             timer_tick = WAIT_TIME;
             return WAIT;
         }
         else
         {
             timer_tick--;
             if(timer_tick > (WAIT_TIME -MASS_TIME))
             {
                 //这段时间MBUS总线有乱码，需要清空内存池，防止对搜表逻辑造成误判
             }
             if(timer_tick == 0)//时间到
             {
                 /***************单片机程序需要通过协议解析判断搜表结果****************/
                 int i;
                 int match_cnt = 0;//匹配成功的次数
                 int match_idx;
                 for(i = 1; i < ARRAY_SIZE(meterNum2); i++)
                 {
                     int8_t ret = compare_meter_addr(meterNum2[i], wildcard);
                     //DEBUG("%d\r\n",ret);
                     if(0 == ret)
                     {
                         match_cnt++;
                         match_idx = i;
                     }
                 }

                 switch(match_cnt)
                 {
                     case 0: return NONE;
                     case 1: return match_idx;
                     default:return COLLIDE;
                 }
                 /************************************************************/
             }
             else
             {
                 return WAIT;
             }

         }
     return WAIT;
}


void discovery_meter_hook_10ms(int *run_flag)
{

       static int cur_idx = 0;
       static int search_cnt=0,find_cnt=0,multi_cnt=0;

       if(!discovery_is_searching(&discover_meter))
        {
              (*run_flag) = 0;
              return ;
        }
#if DISCOVERY_ORDER
        reverse(wildcard_bak,DISCOVERY_MAX_LAYER);
#endif

        int res = discovery_meter_proto_handler(wildcard_bak);
        switch(res)
        {
            case WAIT:
                return ;

            case NONE:
                 discovery_get_none_meter(&discover_meter);
                 break;

            case COLLIDE:
                multi_cnt++;
                discovery_meters_collide(&discover_meter);
                break;

            default:
                 find_cnt++;
                 discovery_get_one_meter(&discover_meter);
                 break;
        }

#if DISCOVERY_DEBUG  //开启打印调试
        cur_idx = DISCOVERY_MAX_LAYER - 1 - cnt_09_in_wildcard_reverse(discover_meter.wildcard);
        search_cnt++;
        DEBUG("[%d]:",search_cnt);
        for(int j=0;j<DISCOVERY_MAX_LAYER;j++)
            DEBUG("0x%02x ",wildcard_bak[j]);
        DEBUG("-- %d ", cur_idx);
        switch(res)
        {
            case WAIT:
                return ;
            case NONE:
                 DEBUG(" match none\r\n");
                 break;
            case COLLIDE:
                DEBUG(" match multi\r\n");
                break;

            default:
                 DEBUG(" match single\r\n");
                 DEBUG("------find = %s,--------(%d)\n", meterNum2[res], find_cnt);//记录
                 break;
        }
#endif
        discovery_meter_get_next_wildcard(&discover_meter,wildcard_bak);//遍历二叉树
        if(!discovery_is_searching(&discover_meter))
        {
            //搜表结束
            DEBUG("搜表结束，搜到%d块表，搜索次数%d，冲突次数%d;",find_cnt, search_cnt,multi_cnt);
            (*run_flag) = 0;
            return ;
        }
        else
        {
            (*run_flag) = 1;
        }
}
